//
// Created by wujehy on 2020/8/3.
//

#ifndef AUTH_RAFT_CONTEXTMANAGER_H
#define AUTH_RAFT_CONTEXTMANAGER_H

#include <map>
#include <memory>
#include "baseType.h"
#include "Context/ContextBase.h"
#include <mutex>

/**
 * @brief 上下文管理器
 */
class ContextManager : public ManagerBase
{
private:
    std::map<int, ContextBase *> m_task_Contxt_map;
    int current_taskid = 1;
    std::mutex _mutex;
public:
    ContextManager();

    void init();

    Type type() override;

    /**
     * @brief 添加一个上下文, 添加成功后 外面new 的上下文指针 的管理权交由 上下文管理器管理 其释放
     * @param [out]taskid 当前添加的上下文id
     * @param [in]context 上下信息
     * @return 返回 true 表示 被管 不需要外部关注指针状态, false 则添加失败 , 需要外部 释放指针否则 会内存泄漏
     */
    bool add(int &taskid, ContextBase *context);

    /**
     * @brief 获去上下文的指针
     * @tparam SubContext 获取的上下文的子类类型
     * @param taskid 需要获取的上下文的任务id
     * @param type 传递 子类型对应的类型
     * @return 返回 SubContext 类型 的 上下文 , 且类型 与type 相同的 上下文 , 查询不到或者类型匹配错误 则返回空指针
     */
    template<typename SubContext>
    SubContext *get(int taskid, int type)
    {
        auto find = m_task_Contxt_map.find( taskid );
        bool isok = false;
        if (find != m_task_Contxt_map.end())
        {
            if (find->second->match() == ContextBase::Match_TYPE)
            {
                isok = (find->second->type() == type);
            } else
            {
                isok = true;
            }

            if (isok)
            {
                SubContext *p = (SubContext *) find->second;
                return p;
            }
        }
        return nullptr;
    }

    /**
     * @brief 通过 类型获取上下文 智能指针的方式返回 返回后 移除管理权限 有外部用户 或 指针指针作用域释放
     * @tparam SubContext 上下文你类型
     * @param taskid 任务id
     * @param type 类型
     * @return 返回 对应智能指针 或空指针
     */
    template<class SubContext>
    std::unique_ptr<SubContext> get_unique_ptr(int taskid, int type)
    {
        auto find = m_task_Contxt_map.find( taskid );
        bool isok = false;
        if (find != m_task_Contxt_map.end())
        {
            if (find->second->match() == ContextBase::Match_TYPE)
            {
                isok = (find->second->type() == type);
            } else
            {
                isok = true;
            }

            if (isok)
            {
                SubContext *p = (SubContext *) find->second;
                m_task_Contxt_map.erase( find->first );
                return std::unique_ptr<SubContext>( p );
            }
        }
    }

    /**
     * @brief 移除一个 任务
     * @param taskid 需要移除的任务id
     */
    void remove(int taskid);

    /**
     * @brief 析钩器
     */
    virtual ~ContextManager();

    /**
     * @brief 初始化完成触发器
     */
    void init_finished() override;

};


#endif //AUTH_RAFT_CONTEXTMANAGER_H
